/***************************************************************************************

***************************************************************************************/
/*!
*************************************************************************************
* \file AEC.c
*
* \brief
*    AEC entropy coding routines
*
* \author
*    Main contributors (see contributors.h for copyright, address and affiliation details)
*    
**************************************************************************************
*/

#include <stdlib.h>
#include <string.h>

#include "global.h"
#include "AEC.h"
#include "memalloc.h"
#include "elements.h"
#include "biaridecod.h"
#include "math.h"
#include "assert.h"

int symbolCount = 0;
int last_dquant = 0;

/***********************************************************************
* L O C A L L Y   D E F I N E D   F U N C T I O N   P R O T O T Y P E S
***********************************************************************
*/
unsigned int unary_bin_decode(DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx,
	int ctx_offset);


unsigned int unary_bin_max_decode(DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx,
	int ctx_offset,
	unsigned int max_symbol);

unsigned int unary_exp_golomb_level_decode( DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx);

unsigned int unary_exp_golomb_mv_decode(DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx,
	unsigned int max_bin);

void CheckAvailabilityOfNeighborsAEC()
{
	int i,j;
	const int mb_width = img->width/MB_SIZE;
	const int mb_nr = img->current_mb_nr;
	Macroblock *currMB = &(mb_data[mb_nr]);
	int check_value;
	for(i=0; i<3; i++)
		for(j=0; j<3; j++)
		{
			mb_data[mb_nr].mb_available[i][j]=NULL;
		}
		mb_data[mb_nr].mb_available[1][1] = &(mb_data[mb_nr]);
		// Check MB to the left
		if(img->pix_x >= MB_SIZE)
		{
			int remove_prediction = currMB->slice_nr != mb_data[mb_nr-1].slice_nr;
			if (!remove_prediction)
			{
				currMB->mb_available[1][0]=&(mb_data[mb_nr-1]);
			}
		}
		// Check MB above
		check_value =  (img->pix_y >= MB_SIZE);
		if(check_value) 
		{
			int remove_prediction = currMB->slice_nr != mb_data[mb_nr-mb_width].slice_nr;
			// upper blocks
			if (!remove_prediction)
			{
				currMB->mb_available[0][1]=&(mb_data[mb_nr-mb_width]);
			}
		}
		// Check MB left above
		if(img->pix_y >= MB_SIZE && img->pix_x >= MB_SIZE)
		{
			int remove_prediction = currMB->slice_nr != mb_data[mb_nr-mb_width-1].slice_nr;
			if (!remove_prediction)
			{
				currMB->mb_available[0][0]=&(mb_data[mb_nr-mb_width-1]);
			}
		}

		// Check MB right above
		if(img->pix_y >= MB_SIZE && img->pix_x < (img->width-MB_SIZE ))
		{
			if(currMB->slice_nr == mb_data[mb_nr-mb_width+1].slice_nr)
				currMB->mb_available[0][2]=&(mb_data[mb_nr-mb_width+1]);
		}
		currMB->mb_available_left = currMB->mb_available[1][0];
		currMB->mb_available_up   = currMB->mb_available[0][1];
		currMB->mbAddrA = mb_nr - 1;
		currMB->mbAddrB = mb_nr - img->PicWidthInMbs;
		currMB->mbAddrC = mb_nr - img->PicWidthInMbs + 1;
		currMB->mbAddrD = mb_nr - img->PicWidthInMbs - 1;

		currMB->mbAvailA = (currMB->mb_available[1][0]!=NULL)?1:0;
		currMB->mbAvailB = (currMB->mb_available[0][1]!=NULL)?1:0;
		currMB->mbAvailC = (currMB->mb_available[0][2]!=NULL)?1:0;
		currMB->mbAvailD = (currMB->mb_available[0][0]!=NULL)?1:0;		
}

void AEC_new_slice()
{
	last_dquant=0;
}

/*!
************************************************************************
* \brief
*    Allocation of contexts models for the motion info
*    used for arithmetic decoding
*
************************************************************************
*/
MotionInfoContexts* create_contexts_MotionInfo(void)
{
	MotionInfoContexts *deco_ctx;

	deco_ctx = (MotionInfoContexts*) calloc(1, sizeof(MotionInfoContexts) );
	if( deco_ctx == NULL )
		no_mem_exit("create_contexts_MotionInfo: deco_ctx");

	return deco_ctx;
}


/*!
************************************************************************
* \brief
*    Allocates of contexts models for the texture info
*    used for arithmetic decoding
************************************************************************
*/
TextureInfoContexts* create_contexts_TextureInfo(void)
{
	TextureInfoContexts *deco_ctx;

	deco_ctx = (TextureInfoContexts*) calloc(1, sizeof(TextureInfoContexts) );
	if( deco_ctx == NULL )
		no_mem_exit("create_contexts_TextureInfo: deco_ctx");

	return deco_ctx;
}




/*!
************************************************************************
* \brief
*    Frees the memory of the contexts models
*    used for arithmetic decoding of the motion info.
************************************************************************
*/
void delete_contexts_MotionInfo(MotionInfoContexts *deco_ctx)
{
	if( deco_ctx == NULL )
		return;

	free( deco_ctx );

	return;
}


/*!
************************************************************************
* \brief
*    Frees the memory of the contexts models
*    used for arithmetic decoding of the texture info.
************************************************************************
*/
void delete_contexts_TextureInfo(TextureInfoContexts *deco_ctx)
{
	if( deco_ctx == NULL )
		return;

	free( deco_ctx );

	return;
}
/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode a pair of
*    intra prediction modes of a given MB.
************************************************************************
*/
void readIntraPredMode_AEC( SyntaxElement *se, img_params *img, DecodingEnvironmentPtr dep_dp )
{
	BiContextTypePtr pCTX;
	int ctx, symbol;
	pCTX = img->currentSlice->tex_ctx->ipr_contexts;
	symbol = 0; 
	ctx = 0;
	while( biari_decode_symbol(dep_dp, pCTX+ctx)==0 ) {
		symbol += 1;
		ctx ++;
		if( ctx>=3 ) ctx=3;
		if( symbol==4 ){
			break;
		}
	}
	se->value1 = symbol;
#if TRACE
	fprintf(p_trace, "@%d %s\t\t\t%d\n",symbolCount++, se->tracestring, se->value1);
	fflush(p_trace);
#endif
}

void readIntraSplite_AEC(SyntaxElement *se, img_params *img, DecodingEnvironmentPtr dep_dp)
{
    BiContextTypePtr pCTX;
    int symbol;
    pCTX = img->currentSlice->tex_ctx->qsplit_contexts;
    symbol = biari_decode_symbol(dep_dp, pCTX);
   
    se->value1 = symbol;
#if TRACE
    fprintf(p_trace, "@%d %s\t\t\t%d\n", symbolCount++, se->tracestring, se->value1);
    fflush(p_trace);
#endif
}

/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode the chroma
*    intra prediction mode of a given MB.
************************************************************************
*/  //GB
void readCIPredMode_AEC(SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	BiContextTypePtr pCTX;
	int ctx, symbol;
	pCTX = img->currentSlice->tex_ctx->cipr_contexts;
	symbol = 0; 
	ctx = 0;
	while( biari_decode_symbol(dep_dp, pCTX+ctx)==0 ) {
		symbol += 1;
		ctx ++;
		if( ctx>=2 ) ctx=2;
		if( symbol==3 ){
			break;
		}
	}
	se->value1 = symbol;//-1;
#if TRACE
	fprintf(p_trace, "@%d %s\t\t\t%d\n",symbolCount++, se->tracestring, se->value1);
	fflush(p_trace);
#endif
}

/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode the motion
*    vector data of a B-frame MB.
************************************************************************
*/
void readMVD_AEC( SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	int i = img->subblock_x;
	int j = img->subblock_y;
	int a, b;
	int act_ctx;
	int act_sym;
	int mv_local_err;
	int mv_sign;
	int list_idx = se->value2 & 0x01;
	int k = (se->value2>>1); // MVD component
	int bin_idx,sig,l,binary_symbol;
	int golomb_order=0;

	PixelPos block_a, block_b;

	MotionInfoContexts *ctx = img->currentSlice->mot_ctx;

	getLuma8x8Neighbour(img->current_mb_nr, i, j, -1,  0, &block_a);
	getLuma8x8Neighbour(img->current_mb_nr, i, j,  0, -1, &block_b);

	if (block_b.available)
	{
		b = absm(mb_data[block_b.mb_addr].mvd[list_idx][block_b.y][block_b.x][k]);
	}
	else
		b=0;

	if (block_a.available)
	{
		a = absm(mb_data[block_a.mb_addr].mvd[list_idx][block_a.y][block_a.x][k]);
	}
	else
		a = 0;

	if ((mv_local_err=a)<2)
		act_ctx = 0;
	else if (mv_local_err<16)
		act_ctx = 1;
	else
		act_ctx = 2;


	se->context = act_ctx;
	bin_idx = 0;
	binary_symbol =0;

	if (!biari_decode_symbol(dep_dp,&ctx->mv_res_contexts[k][act_ctx]))
		act_sym = 0;
	else if (!biari_decode_symbol(dep_dp,&ctx->mv_res_contexts[k][3]))
		act_sym = 1;
	else if (!biari_decode_symbol(dep_dp,&ctx->mv_res_contexts[k][4]))
		act_sym = 2;
	else if (!biari_decode_symbol(dep_dp,&ctx->mv_res_contexts[k][5]))//1110
	{
		act_sym = 0;
		do
		{
			l=biari_decode_symbol_eq_prob(dep_dp);
			if (l==0) 
			{
				act_sym += (1<<golomb_order); 
				golomb_order++;
			}
		}
		while (l!=1);

		while (golomb_order--)
		{//next binary part
			sig = biari_decode_symbol_eq_prob(dep_dp);
			if (sig==1) 
				binary_symbol |= (1<<golomb_order);
		}
		act_sym+=binary_symbol;

		act_sym=3+act_sym*2;

	}
	else //1111
	{
		act_sym = 0;
		do
		{
			l=biari_decode_symbol_eq_prob(dep_dp);
			if (l==0) 
			{
				act_sym += (1<<golomb_order); 
				golomb_order++;
			}
		}
		while (l!=1);

		while (golomb_order--)
		{//next binary part
			sig = biari_decode_symbol_eq_prob(dep_dp);
			if (sig==1) 
				binary_symbol |= (1<<golomb_order);
		}
		act_sym+=binary_symbol;	  
		act_sym = 4+act_sym*2;

	}



	if (act_sym!=0)
	{
		mv_sign=biari_decode_symbol_eq_prob(dep_dp);
		act_sym =(mv_sign==0)?act_sym:-act_sym;
	}
	se->value1 = act_sym;

#if TRACE
	fprintf(p_trace, "@%d %s\t\t\t%d \n",symbolCount++, se->tracestring, se->value1);
	fflush(p_trace);
#endif
}


/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode the 8x8 block type.
************************************************************************
*/
void read_8x8_PredTypeInfo_AEC (SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	int act_sym = 0;

	MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
	BiContextTypePtr pCTX = ctx->b8_type_contexts[0];
	int act_ctx;

	if( biari_decode_symbol( dep_dp, pCTX ) ) {
		act_sym = 2;
		act_ctx = 3;
	}
	else {
		act_sym = 0;
		act_ctx = 2;
	}

	if( biari_decode_symbol( dep_dp, pCTX + act_ctx) ) {
		++act_sym;
	}
	se->value1 = act_sym;
}

void read_other_PredTypeInfo_AEC (SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	int act_ctx;
	int act_sym;

	MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
	BiContextTypePtr pCTX = ctx->b8_type_contexts[0];

	act_sym = 0;
	if( biari_decode_symbol( dep_dp, pCTX) ) {
		act_sym = 2;
		act_ctx = 1;
		if ( biari_decode_symbol( dep_dp, pCTX + act_ctx) ) {
			++act_sym;
		}
	}
	se->value1 = act_sym;
}

void MHMC_read_16x16_PredTypeInfo_AEC (SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	int act_sym = 0;

	MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
	BiContextTypePtr pCTX = ctx->b8_type_contexts[0];
	int act_ctx;

	if( biari_decode_symbol( dep_dp, pCTX ) ) {
		act_sym = 2;
		act_ctx = 1;
		if ( biari_decode_symbol( dep_dp, pCTX + act_ctx) ) {
			++act_sym;
		}
	}
	se->value1 = act_sym;
}


void MHMC_read_other_PredTypeInfo_AEC (SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	int act_sym = 0;

	MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
	BiContextTypePtr pCTX = ctx->b8_type_contexts[0];
	int act_ctx;
	act_ctx = 0;
	if( biari_decode_symbol( dep_dp, pCTX + act_ctx) ) {
		act_sym ++;
	}
	se->value1 = act_sym;
}


void readMBTransType_AEC( SyntaxElement *se, img_params *img, DecodingEnvironmentPtr dep_dp)
{
    BiContextTypePtr pCTX = img->currentSlice->tex_ctx->tu_size_context;
    se->value1 = biari_decode_symbol(dep_dp, pCTX);
#if TRACE
    fprintf(p_trace, "@%d %s\t\t\t%d\n",symbolCount++, se->tracestring, se->value1);
    fflush(p_trace);
#endif
}

/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode the macroblock
*    type info of a given MB.
************************************************************************
*/
void readMBPartTypeInfo_AEC( SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	int a, b;
	int act_ctx;
	int act_sym;
	int bframe=(img->type==B_IMG);
	int curr_mb_type;


	MotionInfoContexts *ctx = (img->currentSlice)->mot_ctx;
	Macroblock *currMB = &mb_data[img->current_mb_nr];

	if( img->type==I_IMG ) { // INTRA-frame
		curr_mb_type=0;
	}
	else {
		if (bframe) {
			BiContextTypePtr pCTX = ctx->mb_type_contexts[2];
			
			if (currMB->mb_available[0][1] == NULL)
				b = 0;
			else
				b = (( (currMB->mb_available[0][1])->mb_type != 0) ? 1 : 0 );
			if (currMB->mb_available[1][0] == NULL)
				a = 0;
			else
				a = (( (currMB->mb_available[1][0])->mb_type != 0) ? 1 : 0 );

			act_ctx = a + b;

			if( biari_decode_symbol(dep_dp, &ctx->mb_type_contexts[2][act_ctx]) == 0 ) {
				act_sym = 0;
			}
			else {
				act_sym = 1;
				act_ctx = 3;
				while( biari_decode_symbol (dep_dp, pCTX + act_ctx) == 0 ) {
					act_sym++;
					act_ctx++;
					if( act_ctx>=4 ) act_ctx=4;
				}
			}
		}
		else  {		// P-frame
			BiContextTypePtr pCTX = ctx->mb_type_contexts[1];
			act_ctx = 0;
			act_sym = 0;
			while( biari_decode_symbol (dep_dp, pCTX+act_ctx)==0 ) {
				act_sym++;
				act_ctx++;
				if( act_ctx>=3) act_ctx=3;
			}
		}
		curr_mb_type = act_sym;
	}
	se->value1 = curr_mb_type;

#if TRACE
	tracebits2("mb_type", 1, curr_mb_type);
#endif

}


/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode the delta qp
*     of a given MB.
************************************************************************
*/
void readDquant_AEC( SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	MotionInfoContexts *ctx = img->currentSlice->mot_ctx;

	int act_ctx;
	int act_sym;
	int dquant;

	act_ctx = ( (last_dquant != 0) ? 1 : 0);

	act_sym = 1-biari_decode_symbol(dep_dp,ctx->delta_qp_contexts + act_ctx );
	if (act_sym != 0)
	{
		act_ctx = 2;
		act_sym = unary_bin_decode(dep_dp,ctx->delta_qp_contexts+act_ctx,1);
		act_sym++;
	}

	dquant = (act_sym+1)/2;
	if((act_sym & 0x01)==0)                           // lsb is signed bit
		dquant = -dquant;
	se->value1 = dquant;

	last_dquant = dquant;

#if TRACE
	fprintf(p_trace, "@%d %s\t\t\t%d\n",symbolCount++, se->tracestring, se->value1);
	fflush(p_trace);
#endif
}
/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode the coded
*    block pattern of a given MB.
************************************************************************
*/
void readCBP_AEC(SyntaxElement *se,
                img_params *img,
    DecodingEnvironmentPtr dep_dp)
{
    TextureInfoContexts *ctx = img->currentSlice->tex_ctx;
    Macroblock *currMB = &mb_data[img->current_mb_nr];

    int b8, b4, b8add, b4add;
    int b8x, b8y, b4x, b4y;
    int a, b;
    int curr_cbp_ctx;
    int cbp = 0;
    int cbp_bit;

    if (currMB->trans_type == TRANS_2Nx2N) {
        b8add = 4;
    } else {
        b8add = 1;
    }

    //  coding of luma part (bit by bit)
    for (b8 = 0; b8 < 4; b8 += b8add) {
        b8x = b8 & 1;
        b8y = b8 / 2;
        if (currMB->trans_type == TRANS_2Nx2N || currMB->splite_flag[b8] == 0) {
            b4add = 4;
        } else {
            b4add = 1;
        }

        for (b4 = 0; b4 < 4; b4 += b4add) {
            int b8_up = 0xF, b8_left = 0xF; // cbp in 8x8 block, 4bit
            int b8_cbp = cbp >> (4 * b8);
            b4y = b4 / 2;
            b4x = b4 & 1;

            // 1st. get 8x8 neighbour's cbp
            if (b8y == 0) {
                if (currMB->mb_available_up != NULL) {
                    b8_up &= ((currMB->mb_available_up)->cbp) >> (4 * (2 + b8x));
                }
            } else {
                b8_up &= cbp >> (4 * b8x);
            }

            if (b8x == 0) {
                if (currMB->mb_available_left != NULL) {
                    b8_left &= ((currMB->mb_available_left)->cbp) >> (4 * (2 * b8y + 1));
                }
            } else {
                b8_left &= cbp >> (4 * 2 * b8y);
            }

            // 2nd. get a & b
            if (b4y == 0) {
                b = (b8_up & (1 << (2 + b4x))) == 0 ? 1 : 0;   //VG-ADD
            } else {
                b = (b8_cbp & (1 << b4x)) == 0 ? 1 : 0;
            }

            if (b4x == 0) {
                a = (b8_left & (1 << (2 * b4y + 1))) == 0 ? 1 : 0; //VG-ADD
            } else {
                a = (b8_cbp & (1 << (2 * b4y))) == 0 ? 1 : 0;
            }

            curr_cbp_ctx = a + 2 * b;

            if (biari_decode_symbol(dep_dp, ctx->cbp_contexts[0] + curr_cbp_ctx)) {
                if (b4add == 4) {
                    cbp += (0xF << (4 * b8));
                } else {
                    cbp += (0x1 << (4 * b8 + b4));
                }
            }
        }
    }

    if (currMB->trans_type == TRANS_2Nx2N && cbp) {
        cbp = 0xFFFF;
    }

    // chroma cbp
    curr_cbp_ctx = 0;
    cbp_bit = biari_decode_symbol(dep_dp, ctx->cbp_contexts[1] + curr_cbp_ctx);
  
    if (cbp_bit)  {
        curr_cbp_ctx = 1;
        cbp_bit = biari_decode_symbol(dep_dp, ctx->cbp_contexts[1] + curr_cbp_ctx);
        if (cbp_bit) {
            cbp += 0xFF0000;
        } else {
            curr_cbp_ctx = 1;
            cbp_bit = biari_decode_symbol(dep_dp, ctx->cbp_contexts[1] + curr_cbp_ctx);
            cbp += (cbp_bit == 1) ? 0xF00000 : 0xF0000;
        }
    }
    se->value1 = cbp;
    if (!cbp) {
        last_dquant = 0;
    }

#if TRACE
    fprintf(p_trace, "@%d %s\t\t\t\t%d\n",symbolCount++, se->tracestring, se->value1);
    fflush(p_trace);
#endif

}

static const int maxpos       [] = {16, 15, 64, 32, 32, 16,  4, 16/*15*/};
static const int c1isdc       [] = { 1,  0,  1,  1,  1,  1,  1,  0};

static const int type2ctx_bcbp[] = { 0,  1,  2,  2,  3,  4,  5,  6}; // 7
static const int type2ctx_map [] = { 0,  1,  2,  3,  4,  5,  6,  7}; // 8
static const int type2ctx_last[] = { 0,  1,  2,  3,  4,  5,  6,  7}; // 8
static const int type2ctx_one [] = { 0,  1,  2,  3,  3,  4,  5,  6}; // 7
static const int type2ctx_abs [] = { 0,  1,  2,  3,  3,  4,  5,  6}; // 7




//===== position -> ctx for MAP =====
//--- zig-zag scan ----
static const int  pos2ctx_map8x8 [] = { 0,  1,  2,  3,  4,  5,  5,  4,  4,  3,  3,  4,  4,  4,  5,  5,
	4,  4,  4,  4,  3,  3,  6,  7,  7,  7,  8,  9, 10,  9,  8,  7,
	7,  6, 11, 12, 13, 11,  6,  7,  8,  9, 14, 10,  9,  8,  6, 11,
	12, 13, 11,  6,  9, 14, 10,  9, 11, 12, 13, 11 ,14, 10, 12, 14}; // 15 CTX
static const int  pos2ctx_map8x4 [] = { 0,  1,  2,  3,  4,  5,  7,  8,  9, 10, 11,  9,  8,  6,  7,  8,
	9, 10, 11,  9,  8,  6, 12,  8,  9, 10, 11,  9, 13, 13, 14, 14}; // 15 CTX
static const int  pos2ctx_map4x4 [] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 14}; // 15 CTX
static const int* pos2ctx_map    [] = {pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map8x8, pos2ctx_map8x4,
	pos2ctx_map8x4, pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map4x4};
//--- interlace scan ----
static const int  pos2ctx_map8x8i[] = { 0,  1,  1,  2,  2,  3,  3,  4,  5,  6,  7,  7,  7,  8,  4,  5,
	6,  9, 10, 10,  8, 11, 12, 11,  9,  9, 10, 10,  8, 11, 12, 11,
	9,  9, 10, 10,  8, 11, 12, 11,  9,  9, 10, 10,  8, 13, 13,  9,
	9, 10, 10,  8, 13, 13,  9,  9, 10, 10, 14, 14, 14, 14, 14, 14}; // 15 CTX
static const int  pos2ctx_map8x4i[] = { 0,  1,  2,  3,  4,  5,  6,  3,  4,  5,  6,  3,  4,  7,  6,  8,
	9,  7,  6,  8,  9, 10, 11, 12, 12, 10, 11, 13, 13, 14, 14, 14}; // 15 CTX
static const int  pos2ctx_map4x8i[] = { 0,  1,  1,  1,  2,  3,  3,  4,  4,  4,  5,  6,  2,  7,  7,  8,
	8,  8,  5,  6,  9, 10, 10, 11, 11, 11, 12, 13, 13, 14, 14, 14}; // 15 CTX
static const int* pos2ctx_map_int[] = {pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map8x8i,pos2ctx_map8x4i,
	pos2ctx_map4x8i,pos2ctx_map4x4, pos2ctx_map4x4, pos2ctx_map4x4};


//===== position -> ctx for LAST =====
static const int  pos2ctx_last8x8 [] = { 0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
	2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
	3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,
	5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8}; //  9 CTX
static const int  pos2ctx_last8x4 [] = { 0,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,
	3,  3,  3,  3,  4,  4,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8}; //  9 CTX

static const int  pos2ctx_last4x4 [] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15}; // 15 CTX
static const int* pos2ctx_last    [] = {pos2ctx_last4x4, pos2ctx_last4x4, pos2ctx_last8x8, pos2ctx_last8x4,
	pos2ctx_last8x4, pos2ctx_last4x4, pos2ctx_last4x4, pos2ctx_last4x4};





/*!
************************************************************************
* \brief
*    Read Significance MAP
************************************************************************
*/
#define RANGENUM 4
int range_Mean[4][RANGENUM+1]=
{

	{ 0,  5, 13, 19, 65},
	{ 0,  2,  6, 11, 65},
	{ 0,  1,  5, 10, 65},
	{ 0,  1,  4, 65, 65}

};
int range_Min[6][5]=
{

	{ 0,  3, 11, 16, 65},
	{ 0,  1,  5, 65, 65},
	{ 0,  1,  5, 9,  65},
	{ 0,  1,  4, 65, 65},
	{ 0,  1,  7, 65, 65},
	{ 0,  1, 65, 65, 65}

};

int DCT_Level[257];
int DCT_Run[257];
int Pair_Pos = 0;
int DCT_Pairs = -1;
const int T_Chr[5] = { 0,1,2,4,3000};  
int DCT_Block_Size = 0;

void readRunLevel_AEC_Ref( SyntaxElement  *se, img_params *img, DecodingEnvironmentPtr dep_dp )
{
	int pairs, rank, pos;
	int Run, Level, absLevel, symbol;
    int coef_num, pos_shift_offset = 0;
    coef_num = DCT_Block_Size * DCT_Block_Size;

    switch (DCT_Block_Size) {
    case 4:
        pos_shift_offset = 0;
        break;
    case 8:
        pos_shift_offset = 2;
        break;
    case 16:
        pos_shift_offset = 4;
        break;
    }

	//--- read coefficients for whole block ---
	if( DCT_Pairs<0 ) {
		BiContextType (*Primary)[NUM_MAP_CTX];
		BiContextTypePtr pCTX;
		BiContextTypePtr pCTX2;
		int ctx, ctx2, offset;
		if( se->context==LUMA_8x8 ) {
			Primary = img->currentSlice->tex_ctx->map_contexts;
		}
		else {
			Primary = img->currentSlice->tex_ctx->last_contexts;
		}
		//! Decode 
		rank = 0;
		pos = 0;
		for( pairs=0; pairs<coef_num + 1; pairs++ ) {
			pCTX = Primary[rank];
			//! EOB
			if( rank>0) {
				pCTX2 = Primary[5+(pos>>(3+pos_shift_offset))];
				ctx2 = (pos>>1)&0x0f;
				ctx = 0;
				//if( biari_decode_symbol(dep_dp, pCTX+ctx) ) {
				if( biari_decode_symbolW(dep_dp, pCTX+ctx, pCTX2+ctx2) ) {
					break;
				}
			}
			//! Level
			ctx = 1;
			symbol = 0;
			while( biari_decode_symbol(dep_dp, pCTX+ctx)==0 ) {
				symbol += 1;
				ctx ++;
				if( ctx>=2 ) ctx =2;
			}
			absLevel = symbol + 1;
			//! Sign
			if( biari_decode_symbol_eq_prob(dep_dp) ) {
				Level = - absLevel;	
			}
			else {
				Level = absLevel;
			}
#if TRACE
			tracebits2("level", 1, Level);
#endif
			//! Run
			if( absLevel==1 ) { 
				offset = 4;
			}
			else {
				offset = 6;
			}
			symbol = 0;
			ctx = 0;
			while( biari_decode_symbol(dep_dp, pCTX+ctx+offset)==0 ) {
				symbol += 1;
				ctx ++;
				if( ctx>=1 ) ctx =1;
			}
			Run = symbol;
#if TRACE
			tracebits2("run", 1, Run);
#endif
			DCT_Level[pairs] = Level;
			DCT_Run[pairs] = Run;
			if( absLevel>T_Chr[rank] ) {
				if( absLevel<=2 )
					rank = absLevel;
				else if( absLevel<=4 )
					rank = 3;
				else
					rank = 4;
			}
			pos += (Run+1);
			if( pos>=coef_num ) pos = coef_num - 1;
		}
		DCT_Pairs = pairs;
		Pair_Pos = DCT_Pairs;
	}
	//--- set run and level ---
	if( DCT_Pairs>0 ) {
		se->value1 = DCT_Level[Pair_Pos-1];
		se->value2 = DCT_Run[Pair_Pos-1];
		Pair_Pos --;
	}
	else {
		//--- set run and level (EOB) ---
		se->value1 = se->value2 = 0;
	}
	//--- decrement coefficient counter and re-set position ---
	if( (DCT_Pairs--)==0 ) Pair_Pos = 0;
}


/*!
************************************************************************
* \brief
*    arithmetic decoding
************************************************************************
*/
int readSyntaxElement_AEC(SyntaxElement *se, img_params *img, DataPartition *this_dataPart)
{
	int curr_len;
	DecodingEnvironmentPtr dep_dp = &(this_dataPart->de_AEC);

	curr_len = arideco_bits_read(dep_dp);

	// perform the actual decoding by calling the appropriate method
	se->reading(se, img, dep_dp);

	return (se->len = (arideco_bits_read(dep_dp) - curr_len));
}


/*!
************************************************************************
* \brief
*    decoding of unary binarization using one or 2 distinct
*    models for the first and all remaining bins; no terminating
*    "0" for max_symbol
***********************************************************************
*/
unsigned int unary_bin_max_decode(DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx,
	int ctx_offset,
	unsigned int max_symbol)
{
	unsigned int l;
	unsigned int symbol;
	BiContextTypePtr ictx;

	symbol =  biari_decode_symbol(dep_dp, ctx );

	if (symbol==0)
		return 0;
	else
	{
		if (max_symbol == 1)
			return symbol;
		symbol=0;
		ictx=ctx+ctx_offset;
		do
		{
			l=biari_decode_symbol(dep_dp, ictx);
			symbol++;
		}
		while( (l!=0) && (symbol<max_symbol-1) );
		if ((l!=0) && (symbol==max_symbol-1))
			symbol++;
		return symbol;
	}
}


/*!
************************************************************************
* \brief
*    decoding of unary binarization using one or 2 distinct
*    models for the first and all remaining bins
***********************************************************************
*/
unsigned int unary_bin_decode(DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx,
	int ctx_offset)
{
	unsigned int l;
	unsigned int symbol;
	BiContextTypePtr ictx;

	symbol = 1 - biari_decode_symbol(dep_dp, ctx );

	if (symbol==0)
		return 0;
	else
	{
		symbol=0;
		ictx=ctx+ctx_offset;
		do
		{
			l= 1 - biari_decode_symbol(dep_dp, ictx);
			symbol++;
		}
		while( l!=0 );
		return symbol;
	}
}


/*!
************************************************************************
* \brief
*    finding end of a slice in case this is not the end of a frame
*
* Unsure whether the "correction" below actually solves an off-by-one
* problem or whether it introduces one in some cases :-(  Anyway,
* with this change the bit stream format works with AEC again.
* StW, 8.7.02
************************************************************************
*/
int AEC_startcode_follows(img_params *img, int eos_bit)
{
	Slice         *currSlice  = img->currentSlice;
	DataPartition *dP;
	unsigned int  bit;
	DecodingEnvironmentPtr dep_dp;

	dP = &(currSlice->partArr[0]);
	dep_dp = &(dP->de_AEC);

	if( eos_bit )
	{
		bit = biari_decode_final (dep_dp); //GB

#if TRACE
		//  strncpy(se->tracestring, "Decode Sliceterm", TRACESTRING_SIZE);
		fprintf(p_trace, "@%d %s\t\t%d\n",symbolCount++, "Decode Sliceterm", bit);
		fflush(p_trace);
#endif
	}
	else
	{
		bit = 0;
	}

	return (bit==1?1:0);
}





/*!
************************************************************************
* \brief
*    Exp Golomb binarization and decoding of a symbol
*    with prob. of 0.5
************************************************************************
*/
unsigned int exp_golomb_decode_eq_prob( DecodingEnvironmentPtr dep_dp,
	int k)
{
	unsigned int l;
	int symbol = 0;
	int binary_symbol = 0;

	do
	{
		l=biari_decode_symbol_eq_prob(dep_dp);
		if (l==1) 
		{
			symbol += (1<<k); 
			k++;
		}
	}
	while (l!=0);

	while (k--)                             //next binary part
		if (biari_decode_symbol_eq_prob(dep_dp)==1) 
			binary_symbol |= (1<<k);

	return (unsigned int) (symbol+binary_symbol);
}


/*!
************************************************************************
* \brief
*    Exp-Golomb decoding for LEVELS
***********************************************************************
*/
unsigned int unary_exp_golomb_level_decode( DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx)
{
	unsigned int l,k;
	unsigned int symbol;
	unsigned int exp_start = 13;

	symbol = biari_decode_symbol(dep_dp, ctx );

	if (symbol==0)
		return 0;
	else
	{
		symbol=0;
		k=1;
		do
		{
			l=biari_decode_symbol(dep_dp, ctx);
			symbol++;
			k++;
		}
		while((l!=0) && (k!=exp_start));
		if (l!=0)
			symbol += exp_golomb_decode_eq_prob(dep_dp,0)+1;
		return symbol;
	}
}




/*!
************************************************************************
* \brief
*    Exp-Golomb decoding for Motion Vectors
***********************************************************************
*/
unsigned int unary_exp_golomb_mv_decode(DecodingEnvironmentPtr dep_dp,
	BiContextTypePtr ctx,
	unsigned int max_bin)
{
	unsigned int l,k;
	unsigned int bin=1;
	unsigned int symbol;
	unsigned int exp_start = 8;

	BiContextTypePtr ictx=ctx;

	symbol = biari_decode_symbol(dep_dp, ictx );

	if (symbol==0)
		return 0;
	else
	{
		symbol=0;
		k=1;

		ictx++;
		do
		{
			l=biari_decode_symbol(dep_dp, ictx  );
			if ((++bin)==2) ictx++;
			if (bin==max_bin) ictx++;
			symbol++;
			k++;
		}
		while((l!=0) && (k!=exp_start));
		if (l!=0)
			symbol += exp_golomb_decode_eq_prob(dep_dp,3)+1;
		return symbol;
	}
}


/*!
************************************************************************
* \brief
*    Read one byte from AEC-partition. 
*    Bitstream->read_len will be modified
*   
*
* \author
*  
************************************************************************
*/
void readIPCMBytes_AEC(SyntaxElement *sym, Bitstream *currStream)
{
	int read_len = currStream->read_len;
	int code_len = currStream->code_len;
	uchar *buf = currStream->streamBuffer;

	sym->len=8;

	if(read_len<code_len)
		sym->inf=buf[read_len++];

	sym->value1=sym->inf;

	currStream->read_len=read_len;

#if TRACE
	tracebits2(sym->tracestring, sym->len, sym->inf);
#endif

}


/*!
************************************************************************
* \brief
*    This function is used to arithmetically decode the 
*    run length info of the skip mb
************************************************************************
*/
void readRunLenghtFromBuffer_AEC( SyntaxElement *se,
img_params *img,
	DecodingEnvironmentPtr dep_dp)
{
	BiContextTypePtr pCTX;
	int ctx, symbol;
	pCTX = img->currentSlice->tex_ctx->one_contexts[0];
	symbol = 0; 
	ctx = 0;
	while( biari_decode_symbol(dep_dp, pCTX+ctx)==0 ) {
		symbol += 1;
		ctx ++;
		if( ctx>=3 ) ctx=3;
	}
	se->value1 = symbol;
#if TRACE
	fprintf(p_trace, "@%d%s\t\t\t%d\n",symbolCount++, se->tracestring, se->value1);
	fflush(p_trace);
#endif
}

void read_Reffrm_AEC( SyntaxElement *se,
img_params *img,
  DecodingEnvironmentPtr dep_dp)
{
  int act_ctx;
  int act_sym;
  
      BiContextTypePtr pCTX = img->currentSlice->tex_ctx->one_contexts[1];//ctx->mb_type_contexts[1];
      act_ctx = 0;
      act_sym=0;
      while( biari_decode_symbol (dep_dp, pCTX+act_ctx)==0 )
      {
        act_sym++;
        act_ctx++;
        //if( act_ctx>=4 ) act_ctx=4;
        if( act_ctx>=(img->max_ref_num-1) ) act_ctx=(img->max_ref_num-1);

      }
       
  se->value1 = act_sym;

}